package com.dimples.dd.system.controller;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.dimples.dd.common.constant.DDServerConstant;
import com.dimples.dd.common.pojo.PageResult;
import com.dimples.dd.common.result.CommonResult;
import com.dimples.dd.log.core.annotation.ApiLog;
import com.dimples.dd.log.core.enums.OperateTypeEnum;
import com.dimples.dd.system.framework.file.core.utils.FileTypeUtils;
import com.dimples.dd.system.model.form.FileCreateForm;
import com.dimples.dd.system.model.form.FileUploadForm;
import com.dimples.dd.system.model.query.FilePageQuery;
import com.dimples.dd.system.model.vo.FilePageVO;
import com.dimples.dd.system.model.vo.FilePreSignedUrlRespVO;
import com.dimples.dd.system.service.SystemFileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.PermitAll;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import static com.dimples.dd.common.result.CommonResult.success;


@Tag(name = "08.文件存储")
@RestController
@RequestMapping("file")
@Validated
@Slf4j
@RequiredArgsConstructor
public class FileController {

    private final SystemFileService fileService;

    @PostMapping("/upload")
    @Operation(summary = "上传文件", description = "后台直接上传文件")
    @ApiLog(operateType = OperateTypeEnum.UPLOAD, applicationName = DDServerConstant.DD_SERVER_SYSTEM, responseEnable = true)
    public CommonResult<String> uploadFile(FileUploadForm fileUploadForm) throws Exception {
        MultipartFile file = fileUploadForm.getFile();
        String path = fileUploadForm.getPath();
        return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
    }

    @GetMapping("/pre-signed-url")
    @Operation(summary = "获取文件预签名地址", description = "：前端上传文件：用于前端直接上传七牛、阿里云 OSS 等文件存储器")
    @ApiLog(operateType = OperateTypeEnum.SELECT, applicationName = DDServerConstant.DD_SERVER_SYSTEM, responseEnable = true)
    public CommonResult<FilePreSignedUrlRespVO> getFilePreSignedUrl(@RequestParam("path") String path) throws Exception {
        return success(fileService.getFilePreSignedUrl(path));
    }

    @PostMapping
    @Operation(summary = "创建文件", description = "前端上传文件：配合 pre-signed-url 接口，记录上传了上传的文件")
    @ApiLog(operateType = OperateTypeEnum.CREATE, applicationName = DDServerConstant.DD_SERVER_SYSTEM, responseEnable = true)
    public CommonResult<Long> createFile(@Valid @RequestBody FileCreateForm fileCreateForm) {
        return success(fileService.createFile(fileCreateForm));
    }

    @DeleteMapping("/{id}")
    @Operation(summary = "删除文件")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPerm('system:file:delete')")
    @ApiLog(operateType = OperateTypeEnum.DELETE, applicationName = DDServerConstant.DD_SERVER_SYSTEM, responseEnable = true)
    public CommonResult<Boolean> deleteFile(@PathVariable("id") Long id) throws Exception {
        fileService.deleteFile(id);
        return success(true);
    }

    @GetMapping("/{configId}/download/**")
    @PermitAll
    @Operation(summary = "下载文件")
    @Parameter(name = "configId", description = "配置编号", required = true)
    @ApiLog(operateType = OperateTypeEnum.DOWNLOAD, applicationName = DDServerConstant.DD_SERVER_SYSTEM)
    public void getFileContent(HttpServletRequest request,
                               HttpServletResponse response,
                               @PathVariable("configId") Long configId) throws Exception {
        // 获取请求的路径
        String path = StrUtil.subAfter(request.getRequestURI(), "/download/", false);
        if (StrUtil.isEmpty(path)) {
            throw new IllegalArgumentException("结尾的 path 路径必须传递");
        }
        // 解码，解决中文路径的问题
        path = URLUtil.decode(path);

        // 读取内容
        byte[] content = fileService.getFileContent(configId, path);
        if (content == null) {
            log.warn("[getFileContent][configId({}) path({}) 文件不存在]", configId, path);
            response.setStatus(HttpStatus.NOT_FOUND.value());
            return;
        }
        FileTypeUtils.writeAttachment(response, path, content);
    }

    @GetMapping("/page")
    @Operation(summary = "获得文件分页")
    @PreAuthorize("@ss.hasPerm('system:file:query')")
    @ApiLog(operateType = OperateTypeEnum.SELECT, applicationName = DDServerConstant.DD_SERVER_SYSTEM)
    public PageResult<FilePageVO> selectFilePage(@Valid FilePageQuery pageQuery) {
        return fileService.selectFilePage(pageQuery);
    }

}
